package top.chenbn.security.filter;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;
import top.chenbn.guli.common.util.ResponseUtil;
import top.chenbn.guli.common.util.Result;
import top.chenbn.security.security.TokenManager;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 访问过滤器
 *
 * @author chenbn
 * @since 2020-08-01
 */
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
  private TokenManager tokenManager;
  private RedisTemplate redisTemplate;

  public TokenAuthenticationFilter(
      AuthenticationManager authManager, TokenManager tokenManager, RedisTemplate redisTemplate) {
    super(authManager);
    this.tokenManager = tokenManager;
    this.redisTemplate = redisTemplate;
  }

  @Override
  protected void doFilterInternal(
      HttpServletRequest req, HttpServletResponse res, FilterChain chain)
      throws IOException, ServletException {
    logger.info("=================" + req.getRequestURI());
    if (req.getRequestURI().indexOf("admin") == -1) {
      chain.doFilter(req, res);
      return;
    }

    UsernamePasswordAuthenticationToken authentication = null;
    try {
      authentication = getAuthentication(req);
    } catch (Exception e) {
      ResponseUtil.out(res, Result.error());
    }

    if (authentication != null) {
      SecurityContextHolder.getContext().setAuthentication(authentication);
    } else {
      ResponseUtil.out(res, Result.error());
    }
    chain.doFilter(req, res);
  }

  private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
    // token置于header里
    String token = request.getHeader("token");
    if (token != null && !"".equals(token.trim())) {
      String userName = tokenManager.getUserFromToken(token);

      List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
      Collection<GrantedAuthority> authorities = new ArrayList<>();
      for (String permissionValue : permissionValueList) {
        if (StringUtils.isEmpty(permissionValue)) {
          continue;
        }
        SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
        authorities.add(authority);
      }

      if (!StringUtils.isEmpty(userName)) {
        return new UsernamePasswordAuthenticationToken(userName, token, authorities);
      }
      return null;
    }
    return null;
  }
}
